import React, { type ReactNode, useState } from 'react'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { Copy, Check } from 'lucide-react'

interface MarkdownReaderProps extends React.HTMLAttributes<HTMLDivElement> {
  content: string
}

const CodeBlock = ({
  children,
  language
}: {
  children: string
  language?: string
}) => {
  const [copied, setCopied] = useState(false)

  const copyToClipboard = async () => {
    try {
      await navigator.clipboard.writeText(children)
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    } catch (err) {
      console.error('Failed to copy text: ', err)
    }
  }

  return (
    <div className="group relative">
      <pre
        className={cn(
          'bg-gray-100 dark:bg-gray-900 p-4 rounded-lg overflow-x-auto',
          'relative'
        )}
      >
        <code className={language}>{children}</code>
      </pre>
      <div className="absolute right-0 top-0 opacity-100 transition-opacity duration-200 group-hover:opacity-100">
        <Button
          size="icon"
          variant="secondary"
          className="size-5 rounded bg-white/20 text-xs backdrop-blur-sm hover:bg-white dark:bg-gray-700/80 dark:hover:bg-gray-700"
          onClick={copyToClipboard}
        >
          {copied ? (
            <Check className="size-4 text-green-500" />
          ) : (
            <Copy className="size-4" />
          )}
        </Button>
      </div>
    </div>
  )
}

const MarkdownReader = React.forwardRef<HTMLDivElement, MarkdownReaderProps>(
  ({ content, className, ...props }, ref) => {
    const renderMarkdown = (): ReactNode[] => {
      const elements: ReactNode[] = []
      let key = 0

      // Split content by code blocks
      const parts = content.split(/(```[\s\S]*?```)/g)

      parts.forEach((part) => {
        if (part.startsWith('```') && part.endsWith('```')) {
          // Code block
          const match = part.match(/```(\w*)\n([\s\S]*?)```/)
          if (match) {
            const [, language, code] = match
            elements.push(
              <CodeBlock key={key++} language={language}>
                {code.trim()}
              </CodeBlock>
            )
          } else {
            // Handle code blocks without language specification
            const matchNoLang = part.match(/```\n([\s\S]*?)```/)
            if (matchNoLang) {
              const [, code] = matchNoLang
              elements.push(<CodeBlock key={key++}>{code.trim()}</CodeBlock>)
            } else {
              elements.push(<div key={key++}>{part}</div>)
            }
          }
        } else {
          // Regular markdown content
          const html = part
            // Headers
            .replace(
              /^###### (.*$)/gim,
              '<h6 class="text-lg font-bold mt-4 mb-2">$1</h6>'
            )
            .replace(
              /^##### (.*$)/gim,
              '<h5 class="text-xl font-bold mt-4 mb-2">$1</h5>'
            )
            .replace(
              /^#### (.*$)/gim,
              '<h4 class="text-xl font-bold mt-4 mb-2">$1</h4>'
            )
            .replace(
              /^### (.*$)/gim,
              '<h3 class="text-xl font-bold mt-4 mb-2">$1</h3>'
            )
            .replace(
              /^## (.*$)/gim,
              '<h2 class="text-2xl font-bold mt-5 mb-3">$1</h2>'
            )
            .replace(
              /^# (.*$)/gim,
              '<h1 class="text-3xl font-bold mt-6 mb-4">$1</h1>'
            )

            // Horizontal rules
            .replace(
              /^\s*---\s*$/gim,
              '<hr class="my-4 border-gray-300 dark:border-gray-700" />'
            )
            .replace(
              /^\s*\*\*\*\s*$/gim,
              '<hr class="my-4 border-gray-300 dark:border-gray-700" />'
            )
            .replace(
              /^\s*___\s*$/gim,
              '<hr class="my-4 border-gray-300 dark:border-gray-700" />'
            )

            // Bold and italic
            .replace(/\*\*\*(.*?)\*\*\*/g, '<strong><em>$1</em></strong>')
            .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
            .replace(/\*(.*?)\*/g, '<em>$1</em>')
            .replace(/___(.*?)___/g, '<strong><em>$1</em></strong>')
            .replace(/__(.*?)__/g, '<strong>$1</strong>')
            .replace(/_(.*?)_/g, '<em>$1</em>')

            // Strikethrough
            .replace(/~~(.*?)~~/g, '<del>$1</del>')

            // Inline code
            .replace(
              /`(.*?)`/g,
              '<code class="bg-gray-300 dark:bg-gray-800 px-1.5 py-0.5 rounded text-sm">$1</code>'
            )

            // Images ![alt](url)
            .replace(
              /!\[([^\]]*)\]\(([^)]+)\)/g,
              '<img src="$2" alt="$1" class="my-2 max-w-full rounded shadow ml-4" />'
            )

            // Process lists
            // Ordered lists with plus sign
            .replace(/^\+\s(.*$)/gim, '<li data-marker="plus">$1</li>')
            // Unordered lists with asterisk
            .replace(/^\*\s(.*$)/gim, '<li data-marker="asterisk">$1</li>')
            // Unordered lists with dash
            .replace(/^-\s(.*$)/gim, '<li data-marker="dash">$1</li>')
            // Ordered lists with numbers
            .replace(/^\d+\. (.*$)/gim, '<li data-marker="number">$1</li>')

            // Wrap lists appropriately
            .replace(
              /(<li data-marker="plus">.*<\/li>\s*)+/,
              '<ol class="list-decimal pl-5 my-2">$&</ol>'
            )
            .replace(
              /(<li data-marker="number">.*<\/li>\s*)+/,
              '<ol class="list-decimal pl-5 my-2">$&</ol>'
            )
            .replace(
              /(<li data-marker="asterisk">.*<\/li>\s*)+/,
              '<ul class="list-disc pl-5 my-2">$&</ul>'
            )
            .replace(
              /(<li data-marker="dash">.*<\/li>\s*)+/,
              '<ul class="list-disc pl-5 my-2">$&</ul>'
            )

            // Remove data markers
            .replace(/data-marker="plus"/g, '')
            .replace(/data-marker="asterisk"/g, '')
            .replace(/data-marker="dash"/g, '')
            .replace(/data-marker="number"/g, '')

            // Blockquotes
            .replace(
              /^> (.*$)/gim,
              '<blockquote class="border-l-4 border-gray-300 pl-4 py-2 my-3 text-gray-600 dark:text-gray-300 italic">$1</blockquote>'
            )

            // Links
            .replace(
              /\[([^\]]+)\]\(([^)]+)\)/g,
              '<a href="$2" class="text-blue-600 dark:text-blue-400 underline hover:text-blue-800 dark:hover:text-blue-300">$1</a>'
            )

            // Tables
            .replace(/^\|(.+)\|$/gm, (match) => {
              // Skip if it's a separator row
              if (
                match.includes('|:-') ||
                match.includes('| :') ||
                match.includes('|--')
              ) {
                return match
              }
              return `<tr><td>${match
                .slice(1, -1)
                .split('|')
                .join('</td><td>')}</td></tr>`
            })
            .replace(/^\|(?:(-+:?|:-:|:-|:?)\|)+$/gm, '') // Remove separator rows
            .replace(/<tr>.*?<\/tr>(?=<tr>)/gs, (match) => {
              // Convert to table structure
              const rows = match
                .split('<tr>')
                .filter((r) => r)
                .map((r) => r.replace('</tr>', ''))
              if (rows.length > 0) {
                return `<table class="table-auto border-collapse border border-gray-300 dark:border-gray-700 my-2"><tbody>${rows
                  .map((r) => `<tr>${r}</tr>`)
                  .join('')}</tbody></table>`
              }
              return match
            })

            // Paragraphs
            .replace(/\n\n/g, '</p><p class="mb-3">')
            .replace(/^(.*)$/gim, '<p class="mb-3">$1</p>')

            // Clean up empty paragraphs
            .replace(/<p class="mb-3"><\/p>/g, '<div class="my-2"></div>')

          elements.push(
            <div key={key++} dangerouslySetInnerHTML={{ __html: html }} />
          )
        }
      })

      return elements
    }

    return (
      <div
        ref={ref}
        className={cn(
          'prose break-words max-w-full dark:prose-invert',
          'prose-headings:font-bold',
          'prose-a:text-blue-600 prose-a:underline hover:prose-a:text-blue-800',
          'dark:prose-a:text-blue-400 dark:hover:prose-a:text-blue-300',
          'prose-blockquote:font-normal',
          'prose-code:before:content-none prose-code:after:content-none',
          className
        )}
        style={{
          wordBreak: 'break-word',
          overflowWrap: 'break-word',
          width: '100%'
        }}
        {...props}
      >
        <style>{`
          .prose img, .prose table, .prose pre, .prose code, .prose blockquote {
            max-width: 100%;
            box-sizing: border-box;
            word-break: break-word;
          }
          .prose pre {
            white-space: pre-wrap;
            word-break: break-word;
          }
          .prose table {
            display: block;
            overflow-x: auto;
            white-space: nowrap;
          }
          .prose table td, .prose table th {
            border: 1px solid #d1d5db;
            padding: 0.5rem;
            text-align: left;
          }
          .prose table th {
            background-color: #f3f4f6;
            font-weight: 600;
          }
          .dark .prose table td,
          .dark .prose table th {
            border-color: #4b5563;
          }
          .dark .prose table th {
            background-color: #374151;
          }
        `}</style>
        {renderMarkdown()}
      </div>
    )
  }
)

MarkdownReader.displayName = 'MarkdownReader'

export { MarkdownReader }
